import difflib
import random
import time
from datetime import datetime

import pandas as pd
from selenium.common import StaleElementReferenceException


def get_drink_amount(drink_type, drink_number, drink_frequency):
    # if drink_type == '啤酒（酒精含量15-40）':
    #     if drink_number == '少量（啤酒<250-500ml/次，色酒100-150ml/次，白酒<25-50ml/次）':
    #         return random.randint(5, 10)  # 250-500ml
    #     elif drink_number == '中量（啤酒<500-2500ml/次，色酒100-150ml/次，白酒50-250ml/次）':
    #         return random.randint(10, 50)  # 500-2500ml
    #     elif drink_number == '大量（啤酒>2500ml/次，其它酒>250ml/次）':
    #         return random.randint(50, 100)  # >2500ml
    # elif drink_type == '色酒（酒精含量<15）':
    #     if drink_number == '少量（啤酒<250-500ml/次，色酒100-150ml/次，白酒<25-50ml/次）':
    #         return random.randint(2, 3)  # 100-150ml
    #     elif drink_number == '中量（啤酒<500-2500ml/次，色酒100-150ml/次，白酒50-250ml/次）':
    #         return random.randint(2, 3)  # 100-150ml
    #     elif drink_number == '大量（啤酒>2500ml/次，其它酒>250ml/次）':
    #         return random.randint(5, 10)  # >250ml
    # elif drink_type == '白酒（酒精含量≥45）':
    #     if drink_number == '少量（啤酒<250-500ml/次，色酒100-150ml/次，白酒<25-50ml/次）':
    #         return random.randint(1, 2)  # 25-50ml
    #     elif drink_number == '中量（啤酒<500-2500ml/次，色酒100-150ml/次，白酒50-250ml/次）':
    #         return random.randint(3, 5)  # 50-250ml
    #     elif drink_number == '大量（啤酒>2500ml/次，其它酒>250ml/次）':
    #         return random.randint(6, 10)  # >250ml

    # if drink_number == '少量（啤酒<250-500ml/次，色酒100-150ml/次，白酒<25-50ml/次）':
    #
    #     if drink_frequency != '经常（每天喝）':
    #         return 1
    #     return random.randint(1, 2)  # 25-50ml
    # elif drink_number == '中量（啤酒<500-2500ml/次，色酒100-150ml/次，白酒50-250ml/次）':
    #
    #     if drink_frequency != '经常（每天喝）':
    #         return 1
    #
    #     return random.randint(3, 5)  # 50-250ml
    # elif drink_number == '大量（啤酒>2500ml/次，其它酒>250ml/次）':
    #     if drink_frequency != '经常（每天喝）':
    #         return random.randint(1, 2)
    #
    #     return random.randint(6, 10)  # >250ml

    if drink_frequency != '经常（每天喝）':
        return 0

    if drink_frequency != '经常（每天喝）':
        return 0

    if drink_frequency == '经常（每天喝）':
        return random.randint(1, 3)


def is_similar(drug_name, drug_names_set, threshold=0.8):
    """
    判断一个药物名称是否与集合中的任何药物名称相似。

    :param drug_name: 当前待检查的药物名称
    :param drug_names_set: 已知药物名称的集合
    :param threshold: 相似度阈值，默认0.8
    :return: 如果相似的药物存在，则返回True，否则返回False
    """
    for name in drug_names_set:
        # 计算相似度
        similarity = difflib.SequenceMatcher(None, drug_name, name).ratio()

        # 如果相似度达到阈值，返回True
        if similarity >= threshold:
            return True

    # 如果没有找到相似药物，返回False
    return False


def update_exercise_time(sfzh, sport_time, bmi):
    sport_time = int(float(sport_time))
    bmi = float(bmi)
    # 提取出生日期（yyyyMMdd）
    birth_date_str = sfzh[6:14]
    birth_date = datetime.strptime(birth_date_str, "%Y%m%d")
    # 获取当前日期
    today = datetime.today()
    # 计算年龄
    age = today.year - birth_date.year
    if today.month < birth_date.month or (today.month == birth_date.month and today.day < birth_date.day):
        age -= 1  # 还没有过生日，减去一岁
    if bmi >= 24.0:
        is_obese = True
    else:
        is_obese = False

    if age <= 70:
        if sport_time < 60 and not is_obese:
            return sport_time + 20
        elif sport_time < 50 and is_obese:
            return sport_time + 30
        else:
            return sport_time
    else:
        if sport_time < 30 and not is_obese:
            return sport_time + 20
        elif sport_time < 20 and is_obese:
            return sport_time + 30
        else:
            return sport_time


def update_staple_food(bmi, staple_food):
    bmi = float(bmi)

    if bmi < 18.5:
        if staple_food > 200:
            staple_food = max(staple_food - 50, 200)
        else:
            staple_food = 200
    elif 18.5 <= bmi < 24.0:
        if staple_food > 200:
            staple_food = max(staple_food - 50, 200)
        else:
            staple_food = 200
    elif 24.0 <= bmi < 28.0:
        if staple_food > 200:
            staple_food = max(staple_food - 50, 200)
        else:
            staple_food = staple_food
    else:
        if staple_food > 200:
            staple_food = max(staple_food - 50, 200)
        else:
            staple_food = staple_food

    return staple_food


def safe_find_element(driver, by, value, retries=3):
    for attempt in range(retries):
        try:
            return driver.find_element(by, value)
        except StaleElementReferenceException:
            if attempt < retries - 1:
                time.sleep(1)  # 等待一会再重试
            else:
                raise


# 定义一个处理不同类型的安全比较函数
def safe_key(value):
    # 将所有值转换为字符串进行比较
    # 如果是 Timestamp 类型，先转换为字符串
    if isinstance(value, pd.Timestamp):
        return str(value)  # 你可以根据需要调整格式
    return str(value)  # 将其他类型转换为字符串


def process_date(new_sf_time):
    # 判断 new_sf_time 是否为 datetime 对象
    if isinstance(new_sf_time, datetime):
        # 如果是 datetime 对象，直接进行格式化
        return new_sf_time.strftime('%Y-%m-%d')

    # 如果是字符串，检查是否符合日期格式
    elif isinstance(new_sf_time, str):
        try:
            # 尝试解析不同的日期格式
            # 假设日期格式有几种常见的格式，可以根据需求调整
            if len(new_sf_time) == 10 and new_sf_time[4] == '-' and new_sf_time[7] == '-':
                # 格式为 'YYYY-MM-DD'
                new_sf_time = datetime.strptime(new_sf_time, '%Y-%m-%d')
                return new_sf_time.strftime('%Y-%m-%d')
            elif len(new_sf_time) == 19 and new_sf_time[4] == '-' and new_sf_time[7] == '-' and new_sf_time[10] == ' ':
                # 格式为 'YYYY-MM-DD HH:MM:SS'
                new_sf_time = datetime.strptime(new_sf_time, '%Y-%m-%d %H:%M:%S')
                return new_sf_time.strftime('%Y-%m-%d')
            else:
                raise ValueError("不支持的日期格式")
        except ValueError as e:
            return str(e)

    # 如果既不是字符串也不是 datetime 对象，返回错误信息
    return "输入无效"


def calculate_age(sfzh):
    """
    根据身份证号计算年龄
    :param sfzh: 身份证号 (str)
    :return: 年龄 (int)
    """
    # 检查身份证号长度是否合法
    if len(sfzh) != 18:
        raise ValueError("身份证号长度不正确，应为18位")

    # 提取出生日期部分（第7到14位）
    birth_date_str = sfzh[6:14]

    # 将出生日期字符串转换为 datetime 对象
    birth_date = datetime.strptime(birth_date_str, "%Y%m%d")

    # 获取当前日期
    today = datetime.today()

    # 计算年龄
    age = today.year - birth_date.year

    # 如果今年生日还没过，年龄减1
    if (today.month, today.day) < (birth_date.month, birth_date.day):
        age -= 1

    return age


def calculate_age2(birthdate):
    """根据出生日期计算精确年龄（年、月、日）"""
    today = datetime.today()
    age = today.year - birthdate.year

    # 如果今年生日还没过，年龄减1
    if (today.month, today.day) < (birthdate.month, birthdate.day):
        age -= 1

    return age


def hypertension_assessment(dbp, sbp, sfzh, sf_time, people_name, doctor_name):
    # 从身份证中提取出生日期
    birthdate_str = sfzh[6:14]  # 提取年月日部分，例如：19901012
    birthdate = datetime.strptime(birthdate_str, "%Y%m%d")  # 转换为日期对象

    dbp = int(dbp)
    sbp = int(sbp)

    # 计算精确年龄
    age = calculate_age2(birthdate)

    # 根据年龄设定血压阈值
    if age >= 65:
        sbp_threshold = 150  # 65岁以上收缩压阈值
        dbp_threshold = 90   # 65岁以上舒张压阈值
    else:
        sbp_threshold = 140  # 65岁以下收缩压阈值
        dbp_threshold = 90   # 65岁以下舒张压阈值

    # 评估血压
    if sbp <= sbp_threshold and dbp <= dbp_threshold:
        return "高血压（血压控制满意）"
    else:
        with open("执行结果/需要追访名单.txt", "a+", encoding="utf-8") as f:
            f.write(f"身份证号-{sfzh}; 舒张压-{dbp}; 收缩压-{sbp}; 随访日期-{sf_time}; 患者姓名-{people_name}; 随访人-{doctor_name}; 血压控制不达标需要追访\n")
        return "高血压（血压控制不满意）"


def diabetes_assessment(blood_glucose, sfzh, sf_time, people_name, doctor_name):
    try:
        blood_glucose = float(blood_glucose)
    except:
        return "糖尿病（血糖控制满意）"
    # 评估血压
    if blood_glucose < 7:
        return "糖尿病（血糖控制满意）"
    else:
        with open("执行结果/需要追访名单.txt", "a+", encoding="utf-8") as f:
            f.write(f"身份证号-{sfzh}; 空腹血糖-{blood_glucose}; 随访日期-{sf_time}; 患者姓名-{people_name}; 随访人-{doctor_name}; 血糖控制不达标需要追访\n")
        return "糖尿病（血糖控制不满意）"


# 重构建议池：每条建议都标记适用的疾病类型
advice_pool = [
    # 核心监测建议（根据疾病类型自动选择）
    {
        "condition": ("高血压", "糖尿病"),
        "advice": "定期监测血压、血糖、足背动脉;"
    },
    {
        "condition": ("高血压",),
        "advice": "定期监测血压、足背动脉;"
    },
    {
        "condition": ("糖尿病",),
        "advice": "定期监测血糖、足背动脉;"
    },

    # 核心通用建议（所有患者都适用）
    {"condition": ("通用",), "advice": "严格遵医嘱用药，注意药物剂量、用法、时间，勿自行更改或停药;"},
    {"condition": ("通用",), "advice": "低盐低脂饮食，每日食盐摄入量不超过5克;"},
    {"condition": ("通用",), "advice": "避免被动吸烟;"},
    {"condition": ("通用",), "advice": "保证7-8小时优质睡眠，避免熬夜;"},

    # 糖尿病专用建议
    {"condition": ("糖尿病",), "advice": "每日监测晨起空腹血糖;"},
    {"condition": ("糖尿病",), "advice": "学习低血糖识别与处理，随身携带糖果;"},
    {"condition": ("糖尿病",), "advice": "每年至少1次眼底检查、肾功能检查;"},
    {"condition": ("糖尿病",), "advice": "足部每日检查，预防糖尿病足;"},
    {"condition": ("糖尿病",), "advice": "限制精制碳水摄入，增加全谷物比例;"},
    {"condition": ("糖尿病",), "advice": "学习食物升糖指数(GI)概念;"},
    {"condition": ("糖尿病",), "advice": "控制餐后2小时血糖在10mmol/L以下;"},
    {"condition": ("糖尿病",), "advice": "记录血糖监测日记;"},

    # 高血压专用建议
    {"condition": ("高血压",), "advice": "每日监测晨起空腹血压;"},
    {"condition": ("高血压",), "advice": "保持情绪稳定，避免情绪剧烈波动;"},
    {"condition": ("高血压",), "advice": "冬季注意保暖，避免寒冷刺激;"},
    {"condition": ("高血压",), "advice": "记录血压监测日记;"},

    # 通用扩展建议
    {"condition": ("通用",), "advice": "烹饪使用植物油，避免动物油脂;"},
    {"condition": ("通用",), "advice": "外出携带疾病卡片和应急药物;"},
    {"condition": ("通用",), "advice": "避免长时间静坐，每小时活动5分钟;"},
    {"condition": ("通用",), "advice": "出现头晕、心悸、视物模糊立即就医;"},
    {"condition": ("通用",), "advice": "定期进行心血管风险评估;"},
    {"condition": ("通用",), "advice": "流感季节前接种疫苗;"},

    # 结尾建议（所有患者都适用）
    {"condition": ("通用",), "advice": "预防并发症，如有不适立即就医，定期复诊;"},
    {"condition": ("通用",), "advice": "若控制不佳或出现异常，建议上级医院就诊"}
]


def generate_doctor_advice(mb_type, pinggu_str):
    """根据疾病类型和评估字符串生成针对性的医生建议组合"""
    advice_list = []

    # 1. 添加监测建议（根据疾病类型）
    for item in advice_pool:
        if isinstance(item, dict) and all(disease in mb_type for disease in item["condition"]):
            advice_list.append(item["advice"])
            break

    # 2. 添加核心通用建议（必选）
    core_advices = [item["advice"] for item in advice_pool
                    if isinstance(item, dict) and "通用" in item["condition"] and "建议" not in item["advice"]]
    # 确保核心建议按顺序添加
    core_advices = core_advices[:4]  # 取前4条核心通用建议
    advice_list.extend(core_advices)

    # 3. 根据评估字符串添加针对性建议
    assessment_advices = []
    if pinggu_str:
        # 根据pg中的不同问题添加针对性建议
        if '血压控制不满意' in pinggu_str:
            assessment_advices.extend([
                "加强血压监测，建议每日测量并记录血压值;",
                "如血压持续偏高，应及时就医调整用药方案;"
            ])
        if '血糖控制不满意' in pinggu_str:
            assessment_advices.extend([
                "加强血糖监测，建议每日测量空腹及餐后血糖;",
                "如血糖持续偏高，应及时就医调整用药方案;"
            ])
        if '超重' in pinggu_str or '肥胖' in pinggu_str:
            assessment_advices.append("加强体重管理，合理控制饮食，增加运动量;")
        if '腹型肥胖' in pinggu_str:
            assessment_advices.append("重点进行腹部脂肪控制，增加有氧运动;")
        if '吸烟' in pinggu_str:
            assessment_advices.append("强烈建议戒烟，可寻求专业戒烟门诊帮助;")
        if '饮酒' in pinggu_str:
            assessment_advices.append("建议限制饮酒，最好戒酒;")
        if '缺乏体育锻炼' in pinggu_str:
            assessment_advices.append("增加体育锻炼，建议每周至少150分钟中等强度运动;")

    # 将评估相关建议添加到列表开头
    advice_list = assessment_advices + advice_list

    # 4. 根据疾病类型筛选相关建议
    disease_specific = []
    general_advices = []

    for item in advice_pool:
        if not isinstance(item, dict):
            continue

        # 跳过已经添加的建议
        if item["advice"] in advice_list:
            continue

        # 收集特定疾病建议
        if "通用" not in item["condition"]:
            if all(disease in mb_type for disease in item["condition"]):
                disease_specific.append(item["advice"])

        # 收集通用建议
        elif "通用" in item["condition"]:
            general_advices.append(item["advice"])

    # 5. 添加疾病特定建议（优先）
    # 根据疾病数量决定添加数量：单病种2-4条，双病种4-6条
    num_disease = len(mb_type) if isinstance(mb_type, (list, tuple)) else 1
    num_to_add = random.randint(2, 4) if num_disease == 1 else random.randint(4, 6)

    if len(disease_specific) > num_to_add:
        advice_list.extend(random.sample(disease_specific, num_to_add))
    else:
        advice_list.extend(disease_specific)

    # 6. 添加通用建议（补充）
    remaining = 15 - len(advice_list)  # 目标总建议数约15条
    if remaining > 0 and general_advices:
        num_general = min(remaining, random.randint(3, 5), len(general_advices))
        advice_list.extend(random.sample(general_advices, num_general))

    # 7. 添加结尾建议
    ending_advices = [item["advice"] for item in advice_pool
                      if isinstance(item, dict) and "建议" in item["advice"]]
    advice_list.extend(ending_advices)

    # 8. 重新编号并组合
    renumbered_advice = ""
    for i, advice in enumerate(advice_list, 1):
        renumbered_advice += f"{i}.{advice}\n"

    return renumbered_advice

if __name__ == '__main__':
    print(generate_doctor_advice("糖尿病"))